﻿'*******************************************************************************************
'* Copyright Brügmann Software GmbH, Papenburg
'* Author: Björn Kremer
'* Contact: codeplex<at>patorg.de
'* 
'* VB.CMIS is a VB.NET implementation of the Content Management Interoperability Services (CMIS) standard
'*
'* This file is part of VB.CMIS.
'* 
'* VB.CMIS is free software: you can redistribute it and/or modify
'* it under the terms of the GNU Lesser General Public License as published by
'* the Free Software Foundation, either version 3 of the License, or
'* (at your option) any later version.
'* 
'* VB.CMIS is distributed in the hope that it will be useful,
'* but WITHOUT ANY WARRANTY; without even the implied warranty of
'* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
'* GNU Lesser General Public License for more details.
'* 
'* You should have received a copy of the GNU Lesser General Public License
'* along with VB.CMIS. If not, see <http://www.gnu.org/licenses/>.
'*******************************************************************************************
Imports System.ServiceModel.Syndication
Imports System.Xml
Imports CMISObjectModel.TypeDefinitions
Imports CMISObjectModel.Constants
Imports CMISObjectModel.CMISObjects
Imports CMISObjectModel.Atom

Namespace Syndication
   Public Class CmisSyndicationFeed
      Inherits SyndicationFeed
      Private _links As List(Of SyndicationLink)
#Region "Constructor"
      ''' <summary>
      ''' Creates an atom entry with the given data
      ''' </summary>
      ''' <param name="data"></param>
      ''' <param name="recursive"></param>
      ''' <param name="baseUri"></param>
      ''' <param name="repositoryId"></param>
      ''' <param name="links"></param>
      ''' <remarks></remarks>
      Public Sub New(data As CMISAtomFeed(Of TypeDefinition), recursive As Boolean, baseUri As Uri, repositoryId As String, links As List(Of SyndicationLink))
         Me.BaseUri = baseUri
         _links = links
         'Set namespaces
         SetInitData()

         'Set atom data(id, title, ...)
         Me.Id = data.AtomId
         Me.LastUpdatedTime = data.AtomLastUpdatedTime
         Me.Title = New TextSyndicationContent(data.AtomTitle)
         If data.AtomAuthors IsNot Nothing Then
            For Each p As SyndicationPerson In data.AtomAuthors
               Me.Authors.Add(p)
            Next
         End If
         'Adds the link to the service document
         SetSericeLink(repositoryId)
         'Add the links from the given data
         For Each link As SyndicationLink In links
            Me.Links.Add(link)
         Next
         SetEntries(data, repositoryId, recursive)
      End Sub
      ''' <summary>
      ''' Creates an atom entry with the given data
      ''' </summary>
      ''' <param name="data"></param>
      ''' <param name="recursive"></param>
      ''' <param name="baseUri"></param>
      ''' <param name="repositoryInfo"></param>
      ''' <param name="links"></param>
      ''' <remarks></remarks>
      Public Sub New(data As CMISAtomFeed(Of CmisObject), recursive As Boolean, baseUri As Uri, repositoryInfo As CMISObjectModel.ServiceDocument.RepositoryInfo, links As List(Of SyndicationLink))
         Me.BaseUri = baseUri
         _links = links
         'Set namespaces
         SetInitData()

         'Set atom data(id, title, ...)
         Me.Id = data.AtomId
         Me.LastUpdatedTime = data.AtomLastUpdatedTime
         Me.Title = New TextSyndicationContent(data.AtomTitle)
         If data.AtomAuthors IsNot Nothing Then
            For Each p As SyndicationPerson In data.AtomAuthors
               Me.Authors.Add(p)
            Next
         End If
         'Adds the link to the service document
         SetSericeLink(repositoryInfo.RepositoryId)
         'Add the links from the given data
         For Each link As SyndicationLink In links
            Me.Links.Add(link)
         Next
         SetEntries(data, repositoryInfo, recursive)
      End Sub
      ''' <summary>
      ''' Adds the needed namespaces
      ''' </summary>
      ''' <remarks></remarks>
      Private Sub SetInitData()
         Me.AttributeExtensions.Add(New XmlQualifiedName("cmis", CmisNamespaceConstants.Xmlns), CmisNamespaceConstants.Cmis)
         Me.AttributeExtensions.Add(New XmlQualifiedName("cmism", CmisNamespaceConstants.Xmlns), CmisNamespaceConstants.Cmism)
         Me.AttributeExtensions.Add(New XmlQualifiedName("atom", CmisNamespaceConstants.Xmlns), CmisNamespaceConstants.Atom)
         Me.AttributeExtensions.Add(New XmlQualifiedName("app", CmisNamespaceConstants.Xmlns), CmisNamespaceConstants.App)
         Me.AttributeExtensions.Add(New XmlQualifiedName("cmisra", CmisNamespaceConstants.Xmlns), CmisNamespaceConstants.Cmisra)
      End Sub
#End Region

#Region "Links"
      ''' <summary>
      ''' Adds the link to the service document
      ''' </summary>
      ''' <param name="id"></param>
      ''' <remarks></remarks>
      Private Sub SetSericeLink(id As String)
         Dim serviceLink As SyndicationLink = CreateSyndicationLink(New Uri(BaseUri, ServiceURIs.GetServiceDocumentById.Replace("{repositoryId}", id).TrimStart("/"c)),
                                                                    CmisAtomLinkConstants.Service,
                                                                    CmisContentTypeConstants.Service)
         Me.Links.Add(serviceLink)
      End Sub

      ''' <summary>
      ''' Returns a atom link with the RelationshipType 'Via' and MediaType 'Entry'
      ''' </summary>
      ''' <param name="uri"></param>
      ''' <returns></returns>
      ''' <remarks></remarks>
      Public Shared Function GetViaLink(uri As Uri) As SyndicationLink
         Return CreateSyndicationLink(uri, CmisAtomLinkConstants.Via, CmisContentTypeConstants.Entry)
      End Function
      ''' <summary>
      ''' Returns a atom link with the RelationshipType 'Self' and the given MediaType
      ''' </summary>
      ''' <param name="uri"></param>
      ''' <param name="selfLinkType"></param>
      ''' <returns></returns>
      ''' <remarks></remarks>
      Public Shared Function GetSelfLink(uri As Uri, selfLinkType As String) As SyndicationLink
         Return CreateSyndicationLink(uri, CmisAtomLinkConstants.Self, selfLinkType)
      End Function
      ''' <summary>
      ''' Returns a atom link with the RelationshipType 'Up' and the given MediaType
      ''' </summary>
      ''' <param name="uri"></param>
      ''' <param name="type"></param>
      ''' <returns></returns>
      ''' <remarks></remarks>
      Public Shared Function GetUpLink(uri As Uri, type As String) As SyndicationLink
         Return CreateSyndicationLink(uri, CmisAtomLinkConstants.Up, type)
      End Function
      ''' <summary>
      ''' Returns a atom link with the RelationshipType 'Down' and MediaType 'Feed'
      ''' </summary>
      ''' <param name="uri"></param>
      ''' <returns></returns>
      ''' <remarks></remarks>
      Public Shared Function GetDownLink(uri As Uri) As SyndicationLink
         Return CreateSyndicationLink(uri, CmisAtomLinkConstants.Down, CmisContentTypeConstants.Feed)
      End Function
      ''' <summary>
      ''' Returns a atom link with the RelationshipType 'Down' and MediaType 'Tree'
      ''' </summary>
      ''' <param name="uri"></param>
      ''' <returns></returns>
      ''' <remarks></remarks>
      Public Shared Function GetDownDescLink(uri As Uri) As SyndicationLink
         Return CreateSyndicationLink(uri, CmisAtomLinkConstants.Down, CmisContentTypeConstants.Tree)
      End Function
      ''' <summary>
      ''' Returns a atom link with the RelationshipType 'FolderTree' and MediaType 'Tree'
      ''' </summary>
      ''' <param name="uri"></param>
      ''' <returns></returns>
      ''' <remarks></remarks>
      Public Shared Function GetFolderTreeLink(uri As Uri) As SyndicationLink
         Return CreateSyndicationLink(uri, CmisAtomLinkConstants.FolderTree, CmisContentTypeConstants.Tree)
      End Function
      ''' <summary>
      ''' Returns a atom link with the RelationshipType 'First' and MediaType 'Feed'
      ''' </summary>
      ''' <param name="uri"></param>
      ''' <returns></returns>
      ''' <remarks></remarks>
      Public Shared Function GetFirstLink(uri As Uri) As SyndicationLink
         Return CreateSyndicationLink(uri, CmisAtomLinkConstants.First, CmisContentTypeConstants.Feed)
      End Function
      ''' <summary>
      ''' Returns a atom link with the RelationshipType 'Next' and MediaType 'Feed'
      ''' </summary>
      ''' <param name="uri"></param>
      ''' <returns></returns>
      ''' <remarks></remarks>
      Public Shared Function GetNextLink(uri As Uri) As SyndicationLink
         Return CreateSyndicationLink(uri, CmisAtomLinkConstants.Next, CmisContentTypeConstants.Feed)
      End Function
      ''' <summary>
      ''' Returns a atom link with the RelationshipType 'Previous' and MediaType 'Feed'
      ''' </summary>
      ''' <param name="uri"></param>
      ''' <returns></returns>
      ''' <remarks></remarks>
      Public Shared Function GetPreviousLink(uri As Uri) As SyndicationLink
         Return CreateSyndicationLink(uri, CmisAtomLinkConstants.Previous, CmisContentTypeConstants.Feed)
      End Function
      ''' <summary>
      ''' Returns a atom link with the RelationshipType 'Last' and MediaType 'Feed'
      ''' </summary>
      ''' <param name="uri"></param>
      ''' <returns></returns>
      ''' <remarks></remarks>
      Public Shared Function GetLastLink(uri As Uri) As SyndicationLink
         Return CreateSyndicationLink(uri, CmisAtomLinkConstants.Last, CmisContentTypeConstants.Feed)
      End Function

      ''' <summary>
      ''' Creates a SyndicationLink from the given data.
      ''' </summary>
      ''' <param name="uri"></param>
      ''' <param name="relationshipType"></param>
      ''' <param name="mediaType"></param>
      ''' <returns></returns>
      ''' <remarks></remarks>
      Public Shared Function CreateSyndicationLink(uri As Uri, relationshipType As String, mediaType As String) As SyndicationLink
         Return New SyndicationLink() With { _
            .Uri = uri, _
            .RelationshipType = relationshipType, _
            .MediaType = mediaType _
         }
      End Function
#End Region




#Region "Atom Extensions"

      ''' <summary>
      ''' Number of Totalitems for this request.
      ''' </summary>
      ''' <param name="count"></param>
      ''' <remarks></remarks>
      Private Sub AddNumItems(count As Integer?)
         If count.HasValue Then
            Me.ElementExtensions.Add("numItems", CmisNamespaceConstants.Cmisra, count.Value)
         End If
      End Sub
      ''' <summary>
      ''' Are there more Items?
      ''' </summary>
      ''' <param name="value"></param>
      ''' <remarks></remarks>
      Private Sub AddHasMoreItems(value As Boolean)
         Me.ElementExtensions.Add("hasMoreItems", CmisNamespaceConstants.Cmisra, value)
      End Sub
#End Region
      
      ''' <summary>
      ''' Converts the given data to a 'CmisSyndicationItem' and adds the item to this instance.
      ''' </summary>
      ''' <param name="dataList"></param>
      ''' <param name="repositoryInfo"></param>
      ''' <param name="recursive"></param>
      ''' <remarks></remarks>
      Private Sub SetEntries(dataList As CMISAtomFeed(Of CmisObject), repositoryInfo As CMISObjectModel.ServiceDocument.RepositoryInfo, recursive As Boolean)
         Dim entries As New List(Of SyndicationItem)()
         For Each data As CMISAtomEntryCmisObject In dataList.Entries
            Dim item As CmisSyndicationItem = New CmisSyndicationItem(data, Me.BaseUri, repositoryInfo, recursive, _links)
            entries.Add(item)
         Next
         Me.Items = entries
         'Are there more Items?
         AddHasMoreItems(dataList.HasMoreItems)
         AddNumItems(dataList.TotalItemCount)
      End Sub

      ''' <summary>
      ''' Converts the given data to a 'CmisSyndicationItem' and adds the item to this instance.
      ''' </summary>
      ''' <param name="dataList"></param>
      ''' <param name="repositoryId"></param>
      ''' <param name="recursive"></param>
      ''' <remarks></remarks>
      Private Sub SetEntries(dataList As CMISAtomFeed(Of TypeDefinition), repositoryId As String, recursive As Boolean)
         Dim entries As New List(Of SyndicationItem)()
         For Each data As CMISAtomEntry(Of TypeDefinition) In dataList.Entries
            Dim item As CmisSyndicationItem = New CmisSyndicationItem(data, Me.BaseUri, repositoryId, recursive, _links)
            entries.Add(item)
         Next
         Me.Items = entries
         'Are there more Items?
         AddHasMoreItems(dataList.HasMoreItems)
         AddNumItems(dataList.TotalItemCount)
      End Sub

    
   End Class
End Namespace